﻿using log4net.Filter;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Minio.DataModel.Notification;
using Modules.Corp.Repositories;
using Modules.System.Dept;
using Modules.System.Role;
using Modules.System.Security;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Exceptions;
using SqlSugar;
using StackExchange.Redis;

namespace Modules.System.User
{
    /// <summary>
    /// 系统用户业务逻辑类
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class UserService
    {
        private readonly SecurityRepository securityRepository;
        private readonly UserRepository userRepository;
        private readonly SysRoleRepository sysRoleRepository;
        private readonly SysUserRoleRepository userRoleRepository;
        private readonly IApplicationContext applicationContext;
        private readonly ILogger logger;
        private readonly ISqlSugarClient db;

        public UserService(IApplicationContext applicationContext,
            ILogger<UserService> logger,
            UserRepository userRepository,
            SysRoleRepository sysRoleRepository,
            SecurityRepository securityRepository,
            SysUserRoleRepository userRoleRepository
            , ISqlSugarClient db
            )
        {
            this.applicationContext = applicationContext;
            this.logger = logger;
            this.userRepository = userRepository;
            this.sysRoleRepository = sysRoleRepository;

            this.securityRepository = securityRepository;
            this.userRoleRepository = userRoleRepository;
            this.db = db;
            //_db = db ?? throw new ArgumentNullException(nameof(db));
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="user"></param>
        /// <param name="security"></param>
        /// <returns></returns>
        public void UpdateUser(SysUser user, IEnumerable<int> roleIds)
        {
            if (userRepository.Exists(user.UserId, user))
                throw new BusinessException($"身份证号码:{user.Cardno}已存在");

            try
            {
                applicationContext.Transaction.Begin();//开始事务

                userRepository.Update(user);

                userRoleRepository.DeleteByEntityId(user.UserId);
                List<SysUserRole> roleList = new List<SysUserRole>();
                foreach (var item in roleIds)
                {
                    SysUserRole sysUserRole = new SysUserRole()
                    {
                        UserId = user.UserId,
                        RoleId = item
                    };
                    roleList.Add(sysUserRole);
                }
                userRoleRepository.CreateOrUpdate(user.UserId, roleList);
                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateUser Exception cardno:{user.Cardno}");
                throw new BusinessException("写入用户数据失败");
            }
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="user"></param>
        /// <param name="password"></param>
        /// <param name="roleIds"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateUser(SysUser user, string password, IEnumerable<int> roleIds)
        {
            if (userRepository.Exists(user))
                throw new BusinessException($"身份证号码:{user.Cardno}已存在");

            try
            {
                applicationContext.Transaction.Begin();//开始事务
                SysSecurity security = new();
                security.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
                security.UserType = UserType.SysUser;
                securityRepository.Insert(security);
                user.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
                userRepository.Insert(user);
                List<SysUserRole> roleList = new List<SysUserRole>();
                foreach (var item in roleIds)
                {
                    SysUserRole sysUserRole = new SysUserRole()
                    {
                        UserId = user.UserId,
                        RoleId = item
                    };
                    roleList.Add(sysUserRole);
                }
                userRoleRepository.CreateOrUpdate(user.UserId, roleList);
                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateUser Exception cardno:{user.Cardno}");
                throw new BusinessException("写入用户数据失败");
            }
        }

        /// <summary>
        /// 用户密码认证登录
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="password"></param>
        public SysUser? PasswordSignIn(string cardNo, string password)
        {
            var security = GetUserSecurity(cardNo);
            if (security == null)
                throw new BusinessException("用户名或密码错误");

            if (!SecurityPasswordHelper.CheckPassword(password, security.Password, UserPasswordFormat.SM4))
                throw new BusinessException("用户名或密码错误");

            HandleLogin(security);

            return GetUser(cardNo);
        }

        /// <summary>
        /// 登陆处理
        /// </summary>
        /// <param name="security"></param>
        private void HandleLogin(SysSecurity security)
        {
            securityRepository.UpdateLoginInfoStatus(security, applicationContext.ClientIp, DateTime.Now);
        }

        /// <summary>
        /// 根据身份证号码获取用户
        /// </summary>
        /// <param name="cardNo"></param>
        /// <returns></returns>
        public SysUser? GetUser(string cardNo)
        {
            return userRepository.GetUser(cardNo);
        }

        public SysUser? Get(int id)
        {
            return userRepository.Get(id);
        }

        /// <summary>
        /// 根据身份证号判断是否存在该用户
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool CodeExists(string code)
        {
            return userRepository.CodeExists(code);
        }

        /// <summary>
        /// 根据用户ID获取用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public SysUser? GetUser(int userId)
        {
            return userRepository.Get(userId);
        }

        /// <summary>
        /// 获取用户安全信息
        /// </summary>
        /// <param name="cardNo"></param>
        /// <returns></returns>
        public SysSecurity? GetUserSecurity(string cardNo)
        {
            var user = GetUser(cardNo);
            if (user == null)
                return null;
            return GetUserSecurity(user.UserId);
        }

        /// <summary>
        /// 获取用户安全信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public SysSecurity? GetUserSecurity(int userId)
        {
            var user = GetUser(userId);
            if (user == null)
                return null;
            return securityRepository.Get(user.SecurityId);
        }

        /// <summary>
        /// 用户分页
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<SysUser> GetUsers(UserQuery query, int pageIndex, int pageSize)
        {
            return userRepository.GetUsers(query, pageIndex, pageSize);
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId"></param>
        public void DeleteUser(int userId)
        {
            userRepository.DeleteByEntityId(userId);
        }

        /// <summary>
        /// 删除多个用户
        /// </summary>
        /// <param name="UserIds"></param>
        public void DeleteUserIds(IEnumerable<int> UserIds)
        {
            foreach (var UserId in UserIds)
            {
                DeleteUser(UserId);
            }
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="password"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void UpdatePassword(int id, string password)
        {
            SysSecurity? userSecurity = GetUserSecurity(id);
            userSecurity = userSecurity == null ? new SysSecurity() : userSecurity;
            userSecurity.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
            securityRepository.Update(userSecurity);
        }

        /// <summary>
        /// 事务测试
        /// </summary>
        public SysUserSugar TranTest(int id)
        {
            var user = db.Queryable<SysUserSugar>().InSingle(id);
            var userList1 = db.Queryable<SysUserSugar>().In(2, 51, 52).ToList();
            var userList2 = db.Queryable<SysUserSugar>().In(w => w.Name, "超级管理员", "张摇", "高启强").ToList();
            var userIds = userList2.Select(s => s.UserId).ToList();

            var dept = db.Queryable<SysDeptSugar>().Where(w => w.DeptId == 15).First();
            var deptList1 = db.Queryable<SysDeptSugar>().In(w => w.DeptId, userIds).ToList();

            var innerModel = db.Queryable<SysUserSugar>()
                         .LeftJoin<SysDeptSugar>((a, b) => a.DeptId == b.DeptId)
                         .Where((a, b) => a.Name == "张摇" && !a.IsDeleted)
                         .Select((a, b) => new InnerModel
                         {
                             userId = a.UserId,
                             userName = a.Name,
                             deptId = b.DeptId,
                             deptName = b.Name,
                         })
                         .ToList();

            user.Name = "刘杰123";
            db.Updateable(user).ExecuteCommand();
            throw new Exception("事务回滚测试");

            return user;
            //if (userRepository.Exists(user))
            //    throw new BusinessException($"身份证号码:{user.Cardno}已存在");

            //try
            //{
            //    applicationContext.Transaction.Begin();//开始事务
            //    SysSecurity security = new();
            //    security.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
            //    security.UserType = UserType.SysUser;
            //    securityRepository.Insert(security);
            //    user.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
            //    userRepository.Insert(user);
            //    List<SysUserRole> roleList = new List<SysUserRole>();
            //    foreach (var item in roleIds)
            //    {
            //        SysUserRole sysUserRole = new SysUserRole()
            //        {
            //            UserId = user.UserId,
            //            RoleId = item
            //        };
            //        roleList.Add(sysUserRole);
            //    }
            //    userRoleRepository.CreateOrUpdate(user.UserId, roleList);
            //    applicationContext.Transaction.Complete();//完成事务
            //}
            //catch (Exception ex)
            //{
            //    applicationContext.Transaction.Abort();//回滚事务
            //    logger.LogError(ex, $"CreateUser Exception cardno:{user.Cardno}");
            //    throw new BusinessException("写入用户数据失败");
            //}
        }
    }

    public class InnerModel
    {
        public int userId { get; set; }
        public string userName { get; set; }
        public int deptId { get; set; }
        public string deptName { get; set; }
    }
}